﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.SweptVolume.CApSVSamplingObjectsHandler
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using EngineeringInternalExtension;
using System;
using System.Collections.ObjectModel;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands.SweptVolume;

public class CApSVSamplingObjectsHandler : IApSamplingActivator
{
  private ITxObject m_rootObject;
  private TxObjectList m_objects;
  private bool m_shouldUpdateObjects;
  private bool m_objectsListChanged;
  private bool m_samplingInProgress;
  private TxObjectList m_previousObjectsList;
  private bool m_treatDeviceAsLinks;
  private TxTypeFilter m_unallowedTypesDetector;
  private bool m_shouldIncludeCables;

  public CApSVSamplingObjectsHandler(ITxObject root, bool includeCables)
  {
    this.m_rootObject = root;
    this.m_objects = new TxObjectList();
    this.m_shouldUpdateObjects = false;
    this.m_objectsListChanged = false;
    this.m_previousObjectsList = (TxObjectList) null;
    this.m_samplingInProgress = false;
    this.m_treatDeviceAsLinks = true;
    this.m_shouldIncludeCables = includeCables;
    this.m_unallowedTypesDetector = new TxTypeFilter();
    this.initUnallowedTypeFilter();
  }

  private void initUnallowedTypeFilter()
  {
    this.m_unallowedTypesDetector.AddIncludedType(typeof (TxFrame));
  }

  public virtual void init()
  {
    if (this.m_objects != null)
      this.unregisterAllObservers();
    this.rebuildSampledObjects(this.m_shouldIncludeCables);
    this.m_objectsListChanged = true;
    this.registerAllObservers();
  }

  public virtual bool maySample() => true;

  public virtual void beforeSample()
  {
    this.m_samplingInProgress = true;
    if (!this.m_shouldUpdateObjects)
      return;
    this.rebuildSampledObjects(this.m_shouldIncludeCables);
    this.unregisterObsoleteObjectsObservers();
    this.registerNewObservers();
  }

  public virtual void afterSample() => this.m_samplingInProgress = false;

  public virtual void cleanup() => this.unregisterAllObservers();

  public event samplingOccurenceReachedEventHandler samplingOccurenceReached;

  public ITxObject RootObject => this.m_rootObject;

  public bool ShouldIncludeCables
  {
    get => this.m_shouldIncludeCables;
    set => this.m_shouldIncludeCables = value;
  }

  public TxObjectList getObjectsForSampling()
  {
    TxTypeFilter txTypeFilter = new TxTypeFilter();
    txTypeFilter.AddIncludedType(typeof (ITxComponent));
    txTypeFilter.AddIncludedType(typeof (ITxSafetyObject));
    txTypeFilter.AddIncludedType(typeof (ITxSkidAppearance));
    TxObjectList objList = txTypeFilter.Filter(this.m_objects);
    ((TxObjectList<ITxObject>) objList).AddRange((TxObjectList<ITxObject>) this.GetAllComponentAppearances());
    return this.getVisibleObjects(this.uniqueList(this.flattenList(objList)));
  }

  public bool hasObjectsListChanged()
  {
    bool objectsListChanged = this.m_objectsListChanged;
    this.m_objectsListChanged = false;
    return objectsListChanged;
  }

  public bool TreatDeviceAsLinks
  {
    get => this.m_treatDeviceAsLinks;
    set => this.m_treatDeviceAsLinks = value;
  }

  private TxObjectList GetAllComponentAppearances()
  {
    TxTypeFilter txTypeFilter = new TxTypeFilter();
    txTypeFilter.AddIncludedType(typeof (ITxPartAppearance));
    TxObjectList componentAppearances1 = txTypeFilter.Filter(this.m_objects);
    if (TxEngineeringDataInternal.GlobalGetPartsMode() == 2)
      return componentAppearances1;
    TxObjectList componentAppearances2 = new TxObjectList();
    foreach (ITxObject itxObject in (Collection<ITxObject>) componentAppearances1)
    {
      if ((itxObject as ITxPartAppearance).OriginPart.EngineeringRepresentation is ITxComponent)
        ((Collection<ITxObject>) componentAppearances2).Add(itxObject);
    }
    return componentAppearances2;
  }

  private TxObjectList flattenList(TxObjectList objList)
  {
    TxObjectList txObjectList = new TxObjectList();
    foreach (ITxObject itxObject in (Collection<ITxObject>) objList)
    {
      if (itxObject is ITxGroup)
      {
        TxObjectList objList1 = itxObject is TxCompoundPart || itxObject is TxCompoundResource ? (itxObject as ITxObjectCollection).GetDirectDescendants((ITxTypeFilter) new TxNoTypeFilter()) : throw new Exception("CApSVSamplingObjectsHandler: flattenList: Unsupported group type");
        ((TxObjectList<ITxObject>) txObjectList).Append((TxObjectList<ITxObject>) this.flattenList(objList1));
      }
      else if (this.m_treatDeviceAsLinks && itxObject is ITxDevice)
      {
        ITxDevice itxDevice = itxObject as ITxDevice;
        ((TxObjectList<ITxObject>) txObjectList).Append((TxObjectList<ITxObject>) itxDevice.Links);
        ((Collection<ITxObject>) txObjectList).Add((ITxObject) itxDevice);
      }
      else if (itxObject is ITxCable)
        ((Collection<ITxObject>) txObjectList).Add(itxObject);
      else if (itxObject is ITxSafetyObject)
      {
        if (itxObject.GetAttribute("SAFETY_OBJECT_SWAPPABLE") is TxIntAttribute attribute && attribute.Value == 1)
          ((Collection<ITxObject>) txObjectList).Add(itxObject);
      }
      else if (!this.m_unallowedTypesDetector.DoesPassFilter(itxObject))
        ((Collection<ITxObject>) txObjectList).Add(itxObject);
    }
    return txObjectList;
  }

  private TxObjectList uniqueList(TxObjectList objList)
  {
    TxObjectList txObjectList = new TxObjectList(((Collection<ITxObject>) objList).Count);
    foreach (ITxObject itxObject in (Collection<ITxObject>) objList)
    {
      if (!((Collection<ITxObject>) txObjectList).Contains(itxObject))
        ((Collection<ITxObject>) txObjectList).Add(itxObject);
    }
    return txObjectList;
  }

  private TxObjectList getVisibleObjects(TxObjectList objList)
  {
    TxObjectList visibleObjects = new TxObjectList(((Collection<ITxObject>) objList).Count);
    foreach (ITxObject itxObject in (Collection<ITxObject>) objList)
    {
      if (itxObject is ITxDisplayableObject && this.isVisible(itxObject as ITxDisplayableObject))
        ((Collection<ITxObject>) visibleObjects).Add(itxObject);
    }
    return visibleObjects;
  }

  private bool isVisible(ITxDisplayableObject displayableObject)
  {
    bool flag = false;
    if (displayableObject != null && displayableObject.Visibility == null || displayableObject.Visibility == 1)
      flag = true;
    return flag;
  }

  private void rebuildSampledObjects(bool shouldIncludeCable)
  {
    if (!this.m_rootObject.IsValid())
    {
      this.m_previousObjectsList = new TxObjectList(this.m_objects);
      this.m_objects = new TxObjectList();
      this.m_shouldUpdateObjects = false;
    }
    else
    {
      this.m_previousObjectsList = new TxObjectList(this.m_objects);
      if (this.m_rootObject is ITxLocatableObject)
        this.m_objects = new CApSVAttachmentTraverse(this.m_rootObject as ITxLocatableObject).getAttachedObjects(shouldIncludeCable);
      else if (this.m_rootObject is ITxCable && !shouldIncludeCable)
      {
        this.m_objects = new TxObjectList(0);
      }
      else
      {
        TxObjectList txObjectList = new TxObjectList(1);
        ((Collection<ITxObject>) txObjectList).Add(this.m_rootObject);
        this.m_objects = txObjectList;
      }
      this.m_shouldUpdateObjects = false;
    }
  }

  private void onSampledObjectsChanged()
  {
    this.m_objectsListChanged = true;
    if (this.m_samplingInProgress || this.samplingOccurenceReached == null)
      return;
    this.samplingOccurenceReached((object) this, new EventArgs());
  }

  private void registerAllObservers()
  {
    foreach (ITxObject itxObject in (Collection<ITxObject>) this.m_objects)
      this.registerObjectObservers(itxObject);
  }

  private void registerNewObservers()
  {
    foreach (ITxObject itxObject in (Collection<ITxObject>) this.m_objects)
    {
      if (!((Collection<ITxObject>) this.m_previousObjectsList).Contains(itxObject))
        this.registerObjectObservers(itxObject);
    }
  }

  private void registerObjectObservers(ITxObject obj)
  {
    switch (obj)
    {
      case ITxLocatableObject _:
        this.registerLocatableObservers(obj as ITxLocatableObject);
        goto label_3;
      case ITxCable _:
label_3:
        if (!(obj is ITxDisplayableObject))
          throw new InvalidCastException("CApSVSamplingObjectsHandler: registerObservers : m_objects contains an object which is not an ITxDisplayableObject");
        this.registerDisplayableObservers(obj as ITxDisplayableObject);
        if (obj is ITxComponent)
          this.registerComponentObservers(obj as ITxComponent);
        obj.Deleted += new TxObject_DeletedEventHandler(this.Obj_Deleted);
        break;
      default:
        throw new InvalidCastException("CApSVSamplingObjectsHandler: registerObservers : m_objects contains an object which is not an ITxLocatableObject");
    }
  }

  private void registerLocatableObservers(ITxLocatableObject locatableObj)
  {
    locatableObj.AttachmentChildAdded += new TxLocatableObject_AttachmentChildAddedEventHandler(this.locatableObj_AttachmentChildAdded);
    locatableObj.AttachmentChildRemoved += new TxLocatableObject_AttachmentChildRemovedEventHandler(this.locatableObj_AttachmentChildRemoved);
  }

  private void registerDisplayableObservers(ITxDisplayableObject displayableObj)
  {
    displayableObj.VisibilitySet += new TxDisplayableObject_VisibilitySetEventHandler(this.displayableObj_VisibilitySet);
  }

  private void registerComponentObservers(ITxComponent componentObj)
  {
    componentObj.AttachmentChildAddedToDescendant += new TxComponent_AttachmentChildAddedToDescendantEventHandler(this.componentObj_AttachmentChildAddedToDescendant);
    componentObj.AttachmentChildRemovedFromDescendant += new TxComponent_AttachmentChildRemovedFromDescendantEventHandler(this.componentObj_AttachmentChildRemovedFromDescendant);
  }

  private void unregisterAllObservers()
  {
    foreach (ITxObject itxObject in (Collection<ITxObject>) this.m_objects)
      this.unregisterObjectObservers(itxObject);
  }

  private void unregisterObsoleteObjectsObservers()
  {
    foreach (ITxObject previousObjects in (Collection<ITxObject>) this.m_previousObjectsList)
    {
      if (!((Collection<ITxObject>) this.m_objects).Contains(previousObjects))
        this.unregisterObjectObservers(previousObjects);
    }
  }

  private void unregisterObjectObservers(ITxObject obj)
  {
    switch (obj)
    {
      case ITxLocatableObject _:
        this.unRegisterLocatableObservers(obj as ITxLocatableObject);
        goto label_3;
      case ITxCable _:
label_3:
        if (!(obj is ITxDisplayableObject))
          throw new InvalidCastException("CApSVSamplingObjectsHandler: registerObservers : m_objects contains an object which is not an ITxDisplayableObject");
        this.unRegisterDisplayableObservers(obj as ITxDisplayableObject);
        if (obj is ITxComponent)
          this.unRegisterComponentObservers(obj as ITxComponent);
        obj.Deleted -= new TxObject_DeletedEventHandler(this.Obj_Deleted);
        break;
      default:
        throw new InvalidCastException("CApSVSamplingObjectsHandler: registerObservers : m_objects contains an object which is not an ITxLocatableObject");
    }
  }

  private void unRegisterLocatableObservers(ITxLocatableObject locatableObj)
  {
    locatableObj.AttachmentChildAdded -= new TxLocatableObject_AttachmentChildAddedEventHandler(this.locatableObj_AttachmentChildAdded);
    locatableObj.AttachmentChildRemoved -= new TxLocatableObject_AttachmentChildRemovedEventHandler(this.locatableObj_AttachmentChildRemoved);
  }

  private void unRegisterDisplayableObservers(ITxDisplayableObject displayableObj)
  {
    displayableObj.VisibilitySet -= new TxDisplayableObject_VisibilitySetEventHandler(this.displayableObj_VisibilitySet);
  }

  private void unRegisterComponentObservers(ITxComponent componentObj)
  {
    componentObj.AttachmentChildAddedToDescendant -= new TxComponent_AttachmentChildAddedToDescendantEventHandler(this.componentObj_AttachmentChildAddedToDescendant);
    componentObj.AttachmentChildRemovedFromDescendant -= new TxComponent_AttachmentChildRemovedFromDescendantEventHandler(this.componentObj_AttachmentChildRemovedFromDescendant);
  }

  private void displayableObj_VisibilitySet(
    object sender,
    TxDisplayableObject_VisibilitySetEventArgs args)
  {
    this.onSampledObjectsChanged();
  }

  private void locatableObj_AttachmentChildAdded(
    object sender,
    TxLocatableObject_AttachmentChildAddedEventArgs args)
  {
    this.m_shouldUpdateObjects = true;
    this.onSampledObjectsChanged();
  }

  private void locatableObj_AttachmentChildRemoved(
    object sender,
    TxLocatableObject_AttachmentChildRemovedEventArgs args)
  {
    this.m_shouldUpdateObjects = true;
    this.onSampledObjectsChanged();
  }

  private void componentObj_AttachmentChildAddedToDescendant(
    object sender,
    TxComponent_AttachmentChildAddedToDescendantEventArgs args)
  {
    this.m_shouldUpdateObjects = true;
    this.onSampledObjectsChanged();
  }

  private void componentObj_AttachmentChildRemovedFromDescendant(
    object sender,
    TxComponent_AttachmentChildRemovedFromDescendantEventArgs args)
  {
    this.m_shouldUpdateObjects = true;
    this.onSampledObjectsChanged();
  }

  private void Obj_Deleted(object sender, TxObject_DeletedEventArgs args)
  {
    ITxObject itxObject = sender as ITxObject;
    this.unregisterObjectObservers(itxObject);
    ((Collection<ITxObject>) this.m_objects).Remove(itxObject);
  }
}
